package com.zmjmall.demo.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 前后端分离所有接口日志记录
 *
 * @author zmj
 * @version 2018/7/03
 */
@Aspect
@Component
@Slf4j
@Order(2)
public class LogAspect {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 织入所有controller层来记录日志
     */
    @Pointcut(value = "execution(public * com.zmjmall.demo.controller.*.*(..))")
    public void all() {
    }

    /**
     * 测试切入User 判断是否登录
     *
     * 定义切入点,拦截UserController下的所有方法
     */
   // @Pointcut("execution(public * com.zmjmall.demo.controller.UserController.*(..))")
    public void verify() {
    }

    /**
     * 声明前置通知
     * @param joinPoint
     */
    @Before("all()")
    public void doBefore(JoinPoint joinPoint){
        MethodSignature methodSignature =(MethodSignature) joinPoint.getSignature();
        Object[] args = joinPoint.getArgs();
        log.info(String.format("[请求日志] %s.%s ，参数：%s",methodSignature.getDeclaringTypeName(),
                methodSignature.getName(),args == null? "":Arrays.toString(args)));
    }
    /**
     * 声明最终通知
     *
     * @param joinPoint
     * @throws Throwable
     */
    //@After("verify()")
    public void doAfter(JoinPoint joinPoint) throws Throwable {
        // 接收到请求，记录请求内容
        log.info("doAfter");
    }

    /**
     * 声明后置通知
     * @param result
     */
   // @AfterReturning(returning = "result", pointcut = "verify()")
    public void doAfterReturning(Object result) {
        log.info("执行返回值：" + result);
    }

    /**
     * 声明环绕通知
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    //@Around("verify()")
    public Object doToken(ProceedingJoinPoint joinPoint) throws Throwable {
        //记录起始时间
        long begin = System.currentTimeMillis();
        Object result = "";
        /** 执行目标方法 */
        try{
            result= joinPoint.proceed();
        }
        catch(Exception e){
            log.error("日志记录发生错误, errorMessage: {}", e.getMessage());
        }
        finally{
            /** 记录操作时间 */
            long took = (System.currentTimeMillis() - begin)/1000;
            if (took >= 10) {
                log.error("Service 执行时间为: {}秒", took);
            } else if (took >= 5) {
                log.warn("Service 执行时间为: {}秒", took);
            } else  if (took >= 2) {
                log.info("Service执行时间为: {}秒", took);
            }
        }
        return result;
    }

}
